#ifndef _POP_H_
#define _POP_H_

#include<vector>
#include"chromo.h"
#include"ff.h"

using namespace std;


// for the vector<Chromo> chromos in population at the inital state
const double RESERVE_RATIO = 2.0;

class Pop
{
 protected:
  int size;
  int chromo_size;
  vector<Chromo> chromos;
  double mean_fit;
  const FFBase *ffunc_p;
 public:
  
  // de/constructos
  Pop();
  Pop(int pop_size, int chromo_length, const FFBase &ffunc);
  Pop(const Pop &copy);
  ~Pop();

  //operator overloading
  Pop& operator=(const Pop &copy);

  // for cal_fitness and update, merge the ffunc parameter into the class?
  virtual double cal_fitness(int chromo);
  virtual void update();

  virtual void evolve() = 0;

  virtual double pop_fitness();
  double mean_fitness(double rate = 1.0); // normal mean fitness of a fraction of the population
  double a_mean_fitness(double cr_value);
  double fitness_stdev(double rate = 1.0);
  double a_fitness_stdev(double cr_value);

  int col_similarity(int col);

  int pop_size();
  void print_chromo(int chromo); // to be extend to a range
  void display_info();
  virtual void sort();
  int total_ham_dist(int chromo); // this may be changed to accept a chromo_t input; 
  double ft_diversity(double topr = 1.0);  // fitness diversity of the whole population
  double hd_diversity(double topr = 1.0); // hamming distance diversity of the whole population

  void add_chromo(int num);
  void kill_chromo(int num);
};

class SimpPop: public Pop
{

 public:
  SimpPop(): Pop() {}
  SimpPop(int pop_size, int chromo_length, const FFBase &ffunc): Pop(pop_size, chromo_length, ffunc) {}
  ~SimpPop() {}

  virtual void evolve();

};
#endif
